package com.zsn.demo.test.aqs;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import lombok.extern.slf4j.Slf4j;

/**
 * @program: threadDemo
 * @ClassName MyLock
 * @description:
 * @author: zsn
 * @create: 2024-06-28 19:02
 * @Version 1.0
 **/
public class MyLock implements Lock {

    class MySync extends AbstractQueuedSynchronizer {
         @Override
         protected boolean tryAcquire(int arg) {
             if (compareAndSetState(0,1)){
                 setExclusiveOwnerThread(Thread.currentThread());
                 return true;
             }
             return false;
         }

         @Override
         protected boolean tryRelease(int arg) {
             setExclusiveOwnerThread(null);
             setState(0);
             return true;
         }

         @Override // 是否持有独占锁
         protected boolean isHeldExclusively() {
             return getState() == 1;
         }

         protected Condition newCondition() {
             return new ConditionObject();
         }
     }
     MySync sync = new MySync();

    @Override
    // 尝试，不成功，进入等待队列
    public void lock() {
        sync.acquire(1);
    }

    @Override     // 尝试，不成功，进入等待队列，可打断
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    @Override // 尝试一次，不成功返回，不进入队列
    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    @Override     // 尝试，不成功，进入等待队列，有时限
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(time));
    }

    @Override
    public void unlock() {
        sync.release(1);
    }

    @Override
    public Condition newCondition() {
        return sync.newCondition();
    }


}

@Slf4j
class test{
    public static void main(String[] args) {
        MyLock lock = new MyLock();
        new Thread(()->{
            lock.lock();

            try {
                log.info(Thread.currentThread().getName()+"locking");
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                log.info(Thread.currentThread().getName()+"unLocking");
                lock.unlock();
            }
        },"t1").start();

        new Thread(()->{

            try {
                if (lock.tryLock()){
                    try {
                        log.info(Thread.currentThread().getName()+"locking");

                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        log.info(Thread.currentThread().getName()+"unLocking");
                        lock.unlock();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        },"t2").start();
    }
}